package priv.yiyuan.example.composite;

import java.util.*;

/**
 * Iterable 允许一个对象成为“for-each循环”语句的目标。参见For-each循环
 *
 * @author YiYuan
 * @data 2025/8/27
 * @apoNote
 */
public class Folder implements FileSystemComponent, Iterable<FileSystemComponent> {

    private String name;

    private List<FileSystemComponent> children = new ArrayList<>();

    public Folder(String name) {
        this.name = name;
    }

    /**
     * 返回迭代器对象
     *
     * @return
     */
    @Override
    public Iterator<FileSystemComponent> iterator() {
        return new DepthFirstIterator(children.iterator());
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public long getSize() {

        long totalSize = 0;

        for (FileSystemComponent component : children) {
            totalSize += component.getSize();
        }

        return totalSize;
    }

    @Override
    public void display(String indent) {

        System.out.println(indent + "+ Folder: " + name + " (Total Size: " + getSize() + "KB)");
        for (FileSystemComponent component : children) {
            component.display(indent + "  ");
        }

    }

    @Override
    public void add(FileSystemComponent component) {
        children.add(component);
    }

    @Override
    public void remove(FileSystemComponent component) {
        children.remove(component);
    }

    @Override
    public FileSystemComponent getChild(int i) {
        return children.get(i);
    }

    private static class DepthFirstIterator implements Iterator<FileSystemComponent> {

        // 使用栈来保存迭代器，实现深度优先遍历
        private Stack<Iterator<FileSystemComponent>> stack = new Stack<>();

        // 当前指向的文件系统组件
        private FileSystemComponent currentComponent;

        // 接收一个初始迭代器
        public DepthFirstIterator(Iterator<FileSystemComponent> iterator) {
            // 将初始迭代器压入栈
            stack.push(iterator);
            // 查找并设置第一个组件
            findNextComponent();
        }

        @Override
        public boolean hasNext() {
            // 如果 currentComponent 不为null，表示还有下一个元素
            return currentComponent != null;
        }

        @Override
        public FileSystemComponent next() {

            // 若没有下一个元素则抛出异常
            if (!hasNext()) {
                throw new NoSuchElementException("");
            }

            // 保存当前组件作为返回值
            FileSystemComponent nextComponent = currentComponent;
            // 查找下一个组件
            findNextComponent();
            // 返回之前保存的组件
            return nextComponent;
        }

        private void findNextComponent() {
            // 先将当前组件设置为null
            currentComponent = null;

            // 当栈不为空时进入循环
            while (!stack.empty()) {

                // 获取栈顶的迭代器
                Iterator<FileSystemComponent> iterator = stack.peek();

                // 存在下一个元素
                if (iterator.hasNext()) {

                    // 获取下一个组件
                    FileSystemComponent component = iterator.next();

                    // 如果组件是文件夹
                    if (component instanceof Folder) {

                        // 将文件夹的迭代器压入栈
                        stack.push(((Folder) component).iterator());
                    }

                    // 设置当前组件并返回
                    currentComponent = component;
                    return;
                }
                else {
                    // 当前迭代器没有元素，弹出栈
                    stack.pop();
                }

            }
        }
    }
}
